package com.bsj.travel.def.mqtt.auth;

import cn.hutool.core.util.HexUtil;
import com.bsj.travel.util.StringUtils;
import lombok.Data;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.Serializable;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

/**
 * @author yinhao
 * @version 1.0
 * @description MQTT连接签名方式-三元组方式
 * @date 2023/11/7
 */
@Data
public class MqttSignature implements Serializable {
    private static final long serialVersionUID = -1716326893161097583L;

    /**
     * 用户名[MQTT连接参数]
     */
    private String username;
    /**
     * 密码[MQTT连接参数]
     */
    private String password;
    /**
     * 客户端ID[MQTT连接参数]
     */
    private String clientId;

    /**
     * 产品key
     */
    private String productKey;
    /**
     * 设备号
     */
    private String deviceName;
    /**
     * 秘钥
     */
    private String deviceSecret;
    /**
     * 连接clientId中的时间戳
     */
    private String timestamp;
    /**
     * 请求地址
     */
    private String ip;
    /**
     * 端口
     */
    private String port;


    /**
     * SDK 连接服务器(三元组)
     *
     * @param productKey   产品key
     * @param deviceName   设备名称
     * @param deviceSecret 设备秘钥
     */
    public MqttSignature(String productKey, String deviceName, String deviceSecret, String timestamp) {
        Objects.requireNonNull(productKey, "productKey is null");
        Objects.requireNonNull(deviceName, "deviceName is null");
        Objects.requireNonNull(deviceSecret, "deviceSecret is null");
        this.username = deviceName + "&" + productKey;
        if (StringUtils.isNull(timestamp)) {
            timestamp = Long.toString(System.currentTimeMillis());
        }
        this.password = getPassword(productKey, deviceName, deviceSecret, timestamp);
        this.clientId = getClientId(productKey, deviceName, timestamp);
        this.deviceSecret = null;
        this.timestamp = null;
    }

    private static String getPassword(String productKey, String deviceName, String deviceSecret, String timestamp) {
        String plainPwd = "clientId" + productKey + "." + deviceName + "deviceName" + deviceName
                + "productKey" + productKey + "timestamp" + timestamp;
        return hmacSha256(plainPwd, deviceSecret);
    }

    private static String getClientId(String productKey, String deviceName, String timestamp) {
//        return productKey + "." + deviceName + "|securemode=2,signmethod=hmacsha256,timestamp=" + timestamp + "|";
        return productKey + "." + deviceName + "|timestamp=" + timestamp + ",_v=sdk-c-3.2.0,securemode=3,signmethod=hmacsha256,lan=C,_ss=1,gw=0,ext=0|";
    }

    private static String hmacSha256(String plainText, String key) {
        if (plainText == null || key == null) {
            return null;
        }
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256");
            mac.init(secretKeySpec);
            byte[] hmacResult = mac.doFinal(plainText.getBytes());
            return HexUtil.encodeHexStr(hmacResult);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public boolean doMqttSign(String clientId, String userName, String password) {
        if (!this.clientId.equalsIgnoreCase(clientId)) {
            return false;
        }
        if (!this.username.equalsIgnoreCase(userName)) {
            return false;
        }
        if (!this.password.equalsIgnoreCase(password)) {
            return false;
        }
        return true;
    }

    /**
     * 三元组MQTT上线解析productKey，deviceName，deviceSecret
     *
     * @param clientId
     */
//    public MqttSignature(String clientId) {
//        Objects.requireNonNull(clientId, "clientId is null");
//        this.username = null;
//        this.password = null;
//        this.clientId = null;
//        //a12vKR7z4fs.BSJTESTZF90600002|securemode=2,signmethod=hmacsha256,timestamp=1699345650774|
//        String[] splitClient = clientId.split("\\|");
//        if (splitClient.length < 2) {
//            return;
//        }
//        //k0ahuUwcWMj.20231121
//        String[] prDevStr = splitClient[0].split("\\.");
//        if (prDevStr.length < 2) {
//            return;
//        }
//        //从clientId中解析出产品key和设备号
//        this.productKey = prDevStr[0];
//        this.deviceName = prDevStr[1];
//        //securemode=2,signmethod=hmacsha256,timestamp=1699345650774
//        String[] splitAuth = splitClient[1].split(",");
//        if (splitAuth.length < 3) {
//            return;
//        }
//        //timestamp=1699345650774
//        String[] splitTime = splitAuth[2].split("=");
//        if (splitTime.length < 2) {
//            return;
//        }
//        this.deviceSecret = null;
//        this.timestamp = splitTime[1];
//    }
    public MqttSignature(String clientId) {
        Objects.requireNonNull(clientId, "clientId is null");
        this.username = null;
        this.password = null;
        this.clientId = null;
        //a12vKR7z4fs.BSJTESTZF90600002|securemode=2,signmethod=hmacsha256,timestamp=1699345650774|
        String[] splitClient = clientId.split("\\|");
        if (splitClient.length < 2) {
            return;
        }
        //k0ahuUwcWMj.20231121
        String[] prDevStr = splitClient[0].split("\\.");
        if (prDevStr.length < 2) {
            return;
        }
        //从clientId中解析出产品key和设备号
        this.productKey = prDevStr[0];
        this.deviceName = prDevStr[1];
        //timestamp=2524608000000,_v=sdk-c-3.2.0,securemode=3,signmethod=hmacsha256,lan=C,_ss=1,gw=0,ext=0
        String[] splitAuth = splitClient[1].split(",");
        if (splitAuth.length < 3) {
            return;
        }
        //timestamp=1699345650774
        String[] splitTime = splitAuth[0].split("=");
        if (splitTime.length < 2) {
            return;
        }
        this.deviceSecret = null;
        this.timestamp = splitTime[1];
    }

    public static void main(String[] args) {
        MqttSignature mqttSignature = new MqttSignature("b1dliz8vnc7", "bsj123456789",
                "bf8c2fd88e9848e09fcd505a75b8412b", System.currentTimeMillis() + "");
        System.out.println(mqttSignature);
    }
}
